/***************************************************************************
 *   Copyright (C) 2007 by Grzegorz Latarowski                             *
 *   g.latarowski@gmail.com                                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

// Qt
#include <QImageReader>

// gcommon
#include "gexception.h"

// gdialogs 
#include "gauthorizationdialog.h"

// gwidgets
#include "gconnectionwidget.h"

// local
#include "window.h"
#include "roieditor.h"

const QString AUTOSTOP_XML_VERSION( "0.1" );


#define TAG_RESOLUTION      "cameraResolution"
#define TAG_WIDTH           "width"
#define TAG_HEIGHT          "height"
#define TAG_SERIAL_NUMBER   "cameraSerialNumber"


// TODO develop maybeSave action


// ===========================================================================
//                                 Window
// ===========================================================================


// --------------------------- Window::Window() ------------------------------
Window::Window() : QMainWindow()
{
		// ui
	setupUi( this );

	message( tr("Connect to camera.") );

	// ====================================================
	// setup graphicsROIEditor
	_pRoiEditor = new GRoiEditor();
	if( graphicsView )
	{
		graphicsView->setScene( _pRoiEditor );
		graphicsView->setCacheMode(QGraphicsView::CacheBackground);
		graphicsView->setRenderHint( QPainter::Antialiasing );
	}
		// update timers 
	_markersImageUpdater.setSingleShot( true );
	_markersImageUpdater.setInterval( 1000 );
	connect( _pRoiEditor, SIGNAL( markersChanged() ),
			 &_markersImageUpdater, SLOT( start() ) );
	connect( &_markersImageUpdater, SIGNAL( timeout() ),
			  this, SLOT( sendMarkersImage() ) );
	connect( &_markersImageUpdater, SIGNAL( timeout() ),
			  this, SLOT( sendAreasConfig() ) );
	
	_shutterImageUpdater.setSingleShot( true );
	_shutterImageUpdater.setInterval( 1000 );
	connect( _pRoiEditor, SIGNAL( shutterChanged() ),
			 &_shutterImageUpdater, SLOT( start() ) );
	connect( &_shutterImageUpdater, SIGNAL( timeout() ),
			  this, SLOT( sendShutterImage() ) );
	connect( &_shutterImageUpdater, SIGNAL( timeout() ),
			  this, SLOT( sendAreasConfig() ) );
	
	_roiImageUpdater.setSingleShot( true );
	_roiImageUpdater.setInterval( 1000 );
	connect( _pRoiEditor, SIGNAL( roiChanged() ),
			 &_roiImageUpdater, SLOT( start() ) );
	connect( &_roiImageUpdater, SIGNAL( timeout() ),
			  this, SLOT( sendRoiImage() ) );
	connect( &_roiImageUpdater, SIGNAL( timeout() ),
			  this, SLOT( sendAreasConfig() ) );

	
	_alarmTimer.setSingleShot( true );
	_alarmTimer.setInterval( 400 );
	connect( &_alarmTimer, SIGNAL( timeout() ),
			  _pRoiEditor, SLOT( hideAlarm() ) );
	
	_accelExceededTimer.setSingleShot( true );
	_accelExceededTimer.setInterval( 400 );
	connect( &_accelExceededTimer, SIGNAL( timeout() ),
			  _pRoiEditor, SLOT( hideAccelExceeded() ) );
	
	
	// ====================================================
	// clear pointers 
	_pConnectionWidget    = NULL;

	// ====================================================
	// widgets
	if( toolBar )
	{
// 		toolBar->addAction( actionTmp );
// 		toolBar->addAction( actionLoadImage );
	}
	
	_pConnectionWidget = new GConnectionWidget( this );
	if( toolBarConnection )
	{
		toolBarConnection->addWidget( _pConnectionWidget );
	}

	_pLineSerialNumber = 0;
	if( toolBarSerialNumber )
	{
		QLabel * pLabel = new QLabel( tr( "Camera serial No." ) );
		_pLineSerialNumber = new QLineEdit();
		if( _pLineSerialNumber )
		{
			_pLineSerialNumber->setReadOnly( true );
		}
		toolBarSerialNumber->addWidget( pLabel );
		toolBarSerialNumber->addWidget( _pLineSerialNumber );
	}

// 	if( splitter )
// 	{
// 		QList<int> sizes;
// 		sizes << 640 << 280;
// 		splitter->setSizes( sizes );
// 	}

	if( dockMessages )
	{
		this->addDockWidget( Qt::BottomDockWidgetArea, dockMessages );
	}
		// dock dockPropertyEditor
	if( dockPropertyEditor )
	{
		this->addDockWidget( Qt::RightDockWidgetArea, dockPropertyEditor );
// 		dockPropertyEditor->resize( 200, dockPropertyEditor->height() );
	}
	
	// ====================================================
	// connections 
	
		// connect udp receiver signal from client to view 
	connect( &_autoClient, SIGNAL( newObjectsCoordinates( QList<objectCoordinates> & ) ),
			  _pRoiEditor, SLOT( updateObjects( QList<objectCoordinates> & ) ) );
	connect( &_autoClient, SIGNAL( newPixmap( const QPixmap & ) ),
			  _pRoiEditor, SLOT( updatePixmap( const QPixmap & ) ) );
	connect( &_autoClient, SIGNAL( reportObject( const QString &, bool ) ),
			  SLOT( objectReported( const QString &, bool ) ) );
	connect( &_autoClient, SIGNAL( accelExceeded() ),
			 SLOT( accelExceeded() ) );

	connect( propertyEditor, SIGNAL( itemChanged() ),
			SLOT( sendParams() ) );

	connect( _pConnectionWidget, SIGNAL( connectToHost( const QString & ) ),
			 SLOT( connectToHost( const QString & ) ) );
	connect( _pConnectionWidget, SIGNAL( disconnectFromHost() ),
			 SLOT( disconnectFromHost() ) );
	
	connect( &_autoClient, SIGNAL( disconnected() ),
			  this, SLOT( hostDisconnected() ) );
	connect( &_autoClient, SIGNAL( authorizationFailed( const QString & ) ),
			  this, SLOT( authorizationFailed( const QString & ) ) );
	
	connect( dockPropertyEditor, SIGNAL( visibilityChanged( bool ) ),
			 actionPropertyEditor, SLOT( setChecked( bool ) ) );
	connect( actionPropertyEditor, SIGNAL( triggered( bool ) ),
			 dockPropertyEditor, SLOT( setVisible( bool ) ) );
	
	connect( dockMessages, SIGNAL( visibilityChanged( bool ) ),
			 actionMessages, SLOT( setChecked( bool ) ) );
	connect( actionMessages, SIGNAL( triggered( bool ) ),
			 dockMessages, SLOT( setVisible( bool ) ) );
	
}
// ---------------------------------------------------------------------------


// --------------------------- Window::~Window() -----------------------------
Window::~Window()
{
}
// ---------------------------------------------------------------------------


// -------------------- Window::on_actionTmp_triggered() ---------------------
void Window::on_actionTmp_triggered()
{
	// TODO remove this crap
	
	return;
}
// ---------------------------------------------------------------------------


// ------------------- Window::on_actionNew_triggered() ----------------------
void Window::on_actionNew_triggered()
{
		// clear opened configFileName
	_configFileName.clear();

		// clear regions editor
	if ( _pRoiEditor )
	{
		_pRoiEditor->setDefaultRegions();
	}

	// TODO clear all input widgets 

}
// ---------------------------------------------------------------------------


// -------------------- Window::on_actionOpen_triggered() --------------------
void Window::on_actionOpen_triggered()
{
	QString fileName = QFileDialog::getOpenFileName( this,
			tr( "Open Configuration File" ),
			QDir::currentPath(),
			tr( "Autostop configuration files (*.xml)" ) );
	
	if ( fileName.isEmpty() ) return;
	
	QFile file( fileName );
	if ( !file.open( QFile::ReadOnly | QFile::Text ) )
	{
		QMessageBox::warning( this,
							  tr( "Adjuster" ),
							  tr( "Cannot read file %1:\n%2." )
									  .arg( fileName )
									  .arg( file.errorString() )
							);
		return;
	}
	if ( readConfigFile( &file ) )
	{
		message( tr( "Configuration file \"%1\" loaded" ).arg( fileName ) );

			// configuration succesfully read, store opened fileName 
		_configFileName = fileName;
	}
}
// ---------------------------------------------------------------------------


// -------------------- Window::on_actionSaveAs_triggered() ------------------
void Window::on_actionSaveAs_triggered()
{
	QString fileName = QFileDialog::getSaveFileName( this,
			tr( "Save Configuration File" ),
			QDir::currentPath(),
			tr( "Autostop configuration files (*.xml)" ) );
	
	if ( fileName.isEmpty() ) return;

		// append extension if nessesarry
	if( !fileName.endsWith( ".xml" ) )
	{
		fileName.append( ".xml" );
	}
	
	QFile file( fileName );
	if ( !file.open( QFile::WriteOnly | QFile::Text ) )
	{
		QMessageBox::warning( this,
							  tr( "Adjuster" ),
							  tr( "Cannot write file %1:\n%2." )
									  .arg( fileName )
									  .arg( file.errorString() )
							);
		return;
	}
	
	if ( writeConfigFile( &file ) )
	{
		message( tr( "Configuration file \"%1\" saved" ).arg( fileName ) );

			// configuration succesfully written, store saved fileName
		_configFileName = fileName;
	}
}
// ---------------------------------------------------------------------------


// -------------------- Window::on_actionSave_triggered() --------------------
void Window::on_actionSave_triggered()
{
		// if some config file is opened/saved
	if( !_configFileName.isEmpty() )
	{
		QFile file( _configFileName );
		if ( !file.open( QFile::WriteOnly | QFile::Text ) )
		{
			QMessageBox::warning( this,
								tr( "Adjuster" ),
								tr( "Cannot write file %1:\n%2." )
										.arg( _configFileName )
										.arg( file.errorString() ) );
			return;
		}
		
		if ( writeConfigFile( &file ) )
		{
			message( tr( "Configuration file \"%1\" saved" )
					.arg( _configFileName ) );
		}
	}
	else
	{
			// call save as method
		on_actionSaveAs_triggered();
	}
}
// ---------------------------------------------------------------------------


// ------------------- Window::on_actionLoadImage_triggered() ----------------
void Window::on_actionLoadImage_triggered()
{
	QString dir = ".";
	QString imageFile = QFileDialog::getOpenFileName(
			this,
			tr("Select image file"),
			dir,
			tr("Images (*.bmp *.png *.xpm *.jpg *.jpeg)")
													);
	
	if ( !imageFile.isEmpty() )
	{
		// load content
		
		QPixmap imagePixmap( imageFile );
		if( imagePixmap.isNull() )
		{
			// pixmap is invalid, show warning
			QMessageBox::warning( this,
								  tr("Adjuster Warning"),
								  tr("Cannot open file \"%1\": "
										  "Unrecognized file type." ).arg( imageFile ),
								  QMessageBox::Ok
								);
			return;
		}

		if( _pRoiEditor )
		{
				// load pixmap into ROIEditor
			_pRoiEditor->updatePixmap( imagePixmap );
				// set deafault regios editors
			_pRoiEditor->setDefaultRegions();
		}
			// show status message
		message( tr("Image \"%1\" loaded").arg( imageFile ) );

		on_actionZoomOriginalSize_triggered();
	}
}
// ---------------------------------------------------------------------------


// ------------- Window::on_actionZoomFitToWidth_triggered() -----------------
void Window::on_actionZoomFitToWidth_triggered()
{
	if( !graphicsView ) return;
	
	double w     = (double) graphicsView->sceneRect().width();
	double viewW = (double) graphicsView->size().width();
	double scale = viewW / w;
	
	graphicsView->setMatrix( QMatrix().scale( scale, scale ), false );
}
// ---------------------------------------------------------------------------


// ------------- Window::on_actionZoomFitToHeight_triggered() ----------------
void Window::on_actionZoomFitToHeight_triggered()
{
	if( !graphicsView ) return;
	
	double h     = graphicsView->sceneRect().height();
	double viewH = graphicsView->size().height();
	double scale = viewH / h;
	
	graphicsView->setMatrix( QMatrix().scale( scale, scale ), false );
}
// ---------------------------------------------------------------------------


// ---------------- Window::on_actionZoomIn_triggered() ----------------------
void Window::on_actionZoomIn_triggered()
{
	if( !graphicsView ) return;
	
	graphicsView->scale( 1.2, 1.2 );
}
// ---------------------------------------------------------------------------

    
// -------------  Window::on_actionZoomOut_triggered() -----------------------
void Window::on_actionZoomOut_triggered()
{
	if( !graphicsView ) return;
	
	graphicsView->scale( 1 / 1.2, 1 / 1.2 );
}
// ---------------------------------------------------------------------------


// ----------- Window::on_actionZoomOriginalSize_triggered() -----------------
void Window::on_actionZoomOriginalSize_triggered()
{
	if( !graphicsView ) return;
	
	graphicsView->setMatrix( QMatrix(), false );
}
// ---------------------------------------------------------------------------


// --------------------- Window::zoomFitInWidget() ---------------------------
void Window::zoomFitInWidget()
{
	if( !graphicsView ) return;
	
	double scroolBarOffset = 5;
	
		// get _pixmaps sizes
	double w = (double) graphicsView->sceneRect().width();
	double h = (double) graphicsView->sceneRect().height();
		// get widget sizes
	double viewW = (double) graphicsView->size().width() - scroolBarOffset;
	double viewH = (double) graphicsView->size().height() - scroolBarOffset;
		// calculate scales
	double scaleW = viewW / w;
	double scaleH = viewH / h;
	
		// fit image to width or height (hole image in window)
	if( scaleW > scaleH )
	{
		graphicsView->setMatrix( QMatrix().scale( scaleH, scaleH ), false );
	}
	else
	{
		graphicsView->setMatrix( QMatrix().scale( scaleW, scaleW ), false );
	}
}
// ---------------------------------------------------------------------------


// -------------------- Window::accelExceeded() ------------------------------
void Window::accelExceeded()
{
	if( !_pRoiEditor ) return;

	_pRoiEditor->showAccelExceeded();
		// proceed with hiding an icon 
	_accelExceededTimer.start();
}
// ---------------------------------------------------------------------------


// --------------------- Window::connectToHost() -----------------------------
void Window::connectToHost( const QString & host )
{
		// if client was connect than disconnect
	if ( _autoClient.isConnected() )
	{
		_autoClient.disconnectFromHost();
	}

		// establish connection
	try
	{
		// before connection
			// set wait cursor icon
		setCursor( Qt::WaitCursor );
			// set disonnected
		if( _pConnectionWidget )
		{
			_pConnectionWidget->setDisconnected();
		}
			// show status that connencting
		message( tr( "Connecting to %1..." ).arg( host ) );

			// establish connection
		_autoClient.connectToHost( host, AUTO_PORT );

		// after connection is established
			// restore cursor
		setCursor( Qt::ArrowCursor );
		if( _autoClient.isConnected() )
		{
				// set status
			message( tr( "Connection to %1 established." ).arg( host ) );

				// set connected
			if( _pConnectionWidget )
			{
				_pConnectionWidget->setConnected();
			}

			// process authentication
			GAuthorizationDialog authorizationDialog;
				// set host 
			authorizationDialog.setHost( host );
				// set last login
			authorizationDialog.setLogin( _lastLogin );
				// get userName & password string
			if( authorizationDialog.exec() )
			{
				_autoClient.sendAuthorization( authorizationDialog.login(),
											   authorizationDialog.password()
											 );
				_lastLogin = authorizationDialog.login();
			}
			else
			{
					// break by user
				_autoClient.disconnectFromHost();
					// set disonnected
				if( _pConnectionWidget )
				{
					_pConnectionWidget->setDisconnected();
				}
				return;
			}
			
				// connection established
			connectedSetup();

		}
			// succes
		return;
	}
	catch( const GException& e )
	{
		message( tr("Connection error: %1" ).arg( e.getMessage() ) );
	}
		
	// defaultly - error or disconnected


		// show message
	message( tr( "Disconnected." ) );
		// set disonnected
	if( _pConnectionWidget )
	{
		_pConnectionWidget->setDisconnected();
	}
		// restore cursor
	setCursor( Qt::ArrowCursor );
	
		// disable buttons which requires valid network connection
	if( actionPlay )
	{
		actionPlay->setDisabled( true );
	}
	if( actionStop )
	{
		actionStop->setDisabled( true );
	}
	
}
// ---------------------------------------------------------------------------


// ----------------- Window::connectedSetup() --------------------------------
void Window::connectedSetup()
{
	// --------------------------------
	// read camera configuration

	int width  = -1;
	int height = -1;
	QByteArray cameraConfigurationData;
	try
	{
		cameraConfigurationData = _autoClient.cameraConfig();
	}
	catch( GException & e )
	{
		QMessageBox::critical( this,
							   tr( "Adjuster. Error" ),
							   e.getMessage()
							 );
		return;
	}
	QTextStream in( &cameraConfigurationData );

		// create document
	QDomDocument doc;
	QString errorStr;
	int errorLine;
	int errorColumn;
	if ( !doc.setContent( in.device(), true, &errorStr, &errorLine, &errorColumn ) )
	{
		QMessageBox::information( window(),
								  tr( "Adjuster" ),
								  tr( "Parse error at line %1, "
										  "column %2:\n%3" )
										  .arg( errorLine )
										  .arg( errorColumn )
										  .arg( errorStr )
								);

			// leave, nothing to read 
		return;
	}
	QDomElement element = doc.documentElement();

		// setup camera paramsDescription
	if( propertyEditor )
	{
			// read paramsDescription
		GParamsDescription paramsDescription;
		paramsDescription.fromXml( element );

		propertyEditor->setParamsDescription( paramsDescription );
	}
	
		// get one frame from camera and setup roiEditor
	if( _pRoiEditor )
	{
			// read camera width and height
		QDomElement resolution = element.firstChildElement( TAG_RESOLUTION );
		if( !resolution.isNull() )
		{
			QDomElement widthElement = resolution.firstChildElement( TAG_WIDTH );
			if( !widthElement.isNull() )
			{
				width = widthElement.text().toInt();
			}
			QDomElement heightElement = resolution.firstChildElement( TAG_HEIGHT );
			if( !heightElement.isNull() )
			{
				height = heightElement.text().toInt();
			}
		}
		_pRoiEditor->setSize( QSize( width, height ) );
		_pRoiEditor->readAreasDescription( element );
		
		QByteArray areasConf = _autoClient.areasConfig();
		QTextStream in( &areasConf );
		_pRoiEditor->readFromStream( in );

		_pRoiEditor->updatePixmap( _autoClient.frame() );
	}

		// parse serial number 
	if( _pLineSerialNumber )
	{
		QDomElement serialNumberElement = element.firstChildElement( TAG_SERIAL_NUMBER );
		if( !serialNumberElement.isNull() )
		{
			_pLineSerialNumber->setText( serialNumberElement.text() );
		}
	}

		// refresh params
	if( propertyEditor )
	{
		disconnect( propertyEditor, SIGNAL( itemChanged() ), this, SLOT( sendParams() ) );
		propertyEditor->setParams( _autoClient.params() );
		connect( propertyEditor, SIGNAL( itemChanged() ),
				SLOT( sendParams() ) );
	}
		// enable buttons which requires established network connection
	if( actionStop )
	{
		actionStop->setDisabled( true );
	}
	if( actionPlay )
	{
		actionPlay->setEnabled( true );
	}
}
// ---------------------------------------------------------------------------


// ----------------  Window::disconnectFromHost() ----------------------------
void Window::disconnectFromHost()
{
	if( !_autoClient.isConnected() ) return;
	
		// disconnect 
	try
	{
			// send roi configuratinos before disconnecting, this prevents from
			// not updating configuration on camera if disconnected within
			// 1 second from last hook move
		if( _markersImageUpdater.isActive() )
		{
			sendMarkersImage();
			sendAreasConfig();
			_markersImageUpdater.stop();
		}
		if( _shutterImageUpdater.isActive() )
		{
			sendShutterImage();
			sendAreasConfig();
			_shutterImageUpdater.stop();
		}
		if( _roiImageUpdater.isActive() )
		{
			sendRoiImage();
			sendAreasConfig();
			_roiImageUpdater.stop();
		}
			// actually disconnect
		_autoClient.disconnectFromHost();
			
			// show message
		message( tr( "Disconnected." ) );
	}
	catch( GException & e )
	{
		QMessageBox::warning( this,
							  tr( "Adjuster. Error" ),
							  e.getMessage()
							);
	}
}
// ---------------------------------------------------------------------------


// -------------------- Window::hostDisconnected() ---------------------------
void Window::hostDisconnected()
{
		// show message
	message( tr( "Connection lost." ) );

	disconnectedSetup();
}
// ---------------------------------------------------------------------------


// ----------------------- Window::disconnectedSetup() -----------------------
void Window::disconnectedSetup()
{
		// restore cursor
	setCursor( Qt::ArrowCursor );
		// set disonnected
	if( _pConnectionWidget )
	{
		_pConnectionWidget->setDisconnected();
	}
	
		// disable buttons which requires valid network connection
	if( actionPlay ) actionPlay->setDisabled( true );
	if( actionStop ) actionStop->setDisabled( true );

	if( _pRoiEditor ) _pRoiEditor->clear();

		// clear propertyEditor
	if( propertyEditor ) propertyEditor->setParamsDescription( GParamsDescription() );
		// clear camera SN
	if( _pLineSerialNumber ) _pLineSerialNumber->clear();
	
}
// ---------------------------------------------------------------------------


// -------------------- Window::on_actionPlay_triggered() --------------------
void Window::on_actionPlay_triggered()
{
		// if connection is established then start timer
	if( _autoClient.isConnected() )
	{
		_autoClient.startReceiving();
		if( actionPlay )
		{
			actionPlay->setDisabled( true );
		}
		if( actionStop )
		{
			actionStop->setEnabled( true );
		}
	}
}
// ---------------------------------------------------------------------------


// -------------------- Window::on_actionStop_triggered() --------------------
void Window::on_actionStop_triggered()
{
		// stop streaming video 
	if( _autoClient.isConnected() )
	{
		_autoClient.stopReceiving();
		if( actionPlay )
		{
			actionPlay->setEnabled( true );
		}
		if( actionStop )
		{
			actionStop->setDisabled( true );
		}
	}
}
// ---------------------------------------------------------------------------


// ------------------ Window::authorizationFailed() --------------------------
void Window::authorizationFailed( const QString & message )
{
	QMessageBox::warning( this,
						  tr( "Authorization failed" ),
						  message
						);
}
// ---------------------------------------------------------------------------


// --------------------- Window::updateFrame() -------------------------------
void Window::updateFrame()
{
	try
	{
		startClock();
		if( _pRoiEditor ) _pRoiEditor->updatePixmap( _autoClient.frame() );
		endClock( "reading frame" );
	}
	catch( const GException& e )
	{
		message( tr( "Camera error: %1" ).arg( e.getMessage() ) );
	}
}
// ---------------------------------------------------------------------------


// ------------------------- Window::sendParams() ----------------------------
void Window::sendParams()
{
	if( !_autoClient.isConnected() ) return;
	
	try
	{
		if( propertyEditor )
		{
			_autoClient.sendParams( propertyEditor->params() );
		}
	}
	catch( const GException & e )
	{
		message( tr( "Camera error: %1" ).arg( e.getMessage() ) );
	}
}
// ---------------------------------------------------------------------------


// ----------------------- Window::sendAreasConfig() -------------------------
void Window::sendAreasConfig()
{
	if( !_autoClient.isConnected() && !_pRoiEditor ) return;
	
	try
	{
			// prepare data
		QByteArray buffer;
		QTextStream out( &buffer );
		_pRoiEditor->writeToStream( out );

		_autoClient.sendAreasConfig( buffer );
	}
	catch( const GException & e )
	{
		message( tr( "Camera error: %1" ).arg( e.getMessage() ) );
	}
}
// ---------------------------------------------------------------------------


// ----------------------- Window::message() ---------------------------------
void Window::message( const QString & message, int timeout )
{
		// show message
	if( statusBar() )
	{
		statusBar()->showMessage( message, timeout );
	}
}
// ---------------------------------------------------------------------------


// -------------------- Window::objectReported() -----------------------------
void Window::objectReported( const QString & message, bool highlighted )
{
	Q_ASSERT( textLogger );

	QString text = message;
	if ( highlighted )
	{
		text = QString("<font color=\"red\">%1</font>").arg( message );
	}
	
	textLogger->append( text );

	// if object is bad show and icon
	if( highlighted )
	{
		_pRoiEditor->showAlarm();
		_alarmTimer.start();
	}
}
// ---------------------------------------------------------------------------


// -------------------------- Window::startClock() ---------------------------
void Window::startClock()
{
#ifdef Q_OS_UNIX
    gettimeofday( &_clock, NULL );
#else
    _clock = GetTickCount();
#endif
}
// ---------------------------------------------------------------------------


// ------------------------- Window::endClock() ------------------------------
void Window::endClock( const QString description )
{
    double seconds = 0.0;
#ifdef Q_OS_UNIX
    struct timeval end;
    gettimeofday( &end, NULL );

    seconds = (double)end.tv_sec - (double)_clock.tv_sec + 1E-6*end.tv_usec - 1E-6*_clock.tv_usec;
#else        
    seconds = ( GetTickCount() - _clock ) * 0.001;
#endif
	
    message( QString("%1 : %2 [s]").arg( description ).arg( seconds ) );
}
// ---------------------------------------------------------------------------


// --------------------- Window::writeConfigFile() ---------------------------
bool Window::writeConfigFile( QIODevice * pDevice )
{
	QDomDocument doc( "Autostop" );

		// create root node for the document 
	QDomElement autostop = doc.createElement( "autostop" );
		// create version attribute for root node 
	QDomAttr versionAttr = doc.createAttribute( "version" );
	versionAttr.setValue( AUTOSTOP_XML_VERSION );
	autostop.setAttributeNode( versionAttr );
		// append autostop (root) node to document
	doc.appendChild( autostop );
		// append roi editor settings
	if( _pRoiEditor )
	{
		autostop.appendChild( _pRoiEditor->toXml( doc ) );
	}
		// append params
	if( propertyEditor )
	{
		autostop.appendChild( propertyEditor->params().toXml( doc ) );
	}

		// save file to pDevice 
    const int IndentSize = 4;
    QTextStream out( pDevice );
    doc.save( out, IndentSize );
	
	return true;
}
// ---------------------------------------------------------------------------


// -------------------- Window::readConfigFile() -----------------------------
bool Window::readConfigFile( QIODevice * pDevice )
{
	QDomDocument doc;
	
	QString errorStr;
	int errorLine;
	int errorColumn;
	
	if ( !doc.setContent( pDevice, true, &errorStr, &errorLine, &errorColumn ) )
	{
		QMessageBox::information( window(),
								  tr( "Adjuster" ),
								  tr( "Parse error at line %1, "
										  "column %2:\n%3" )
										  .arg( errorLine )
										  .arg( errorColumn )
										  .arg( errorStr )
								);
		return false;
	}
	
	QDomElement autostopElement = doc.documentElement();
	if ( autostopElement.tagName() != "autostop")
	{
		QMessageBox::information( window(),
								  tr( "Adjuster" ),
								  tr( "The file is not and Autostop "
										  "configuration file." )
								);
		return false;
	}
	else if ( autostopElement.hasAttribute( "version" )
				 && autostopElement.attribute( "version" ) != AUTOSTOP_XML_VERSION )
	{
		QMessageBox::information( window(),
								  tr( "Adjuster" ),
								  tr( "The file is not and Autostop "
										  "configuration file version %1." )
										  .arg( AUTOSTOP_XML_VERSION )
								);
		return false;
	}

	// ====================================================
	// parse elements
	try
	{
			// parse roiEditor
		if( _pRoiEditor )
		{
			_pRoiEditor->fromXml( autostopElement );
		}
			// parse params
		if( propertyEditor )
		{
			GParams params;
			params.fromXml( autostopElement );
			propertyEditor->setParams( params );
		}
	}
	catch( const GDatasetError &e )
	{
		QMessageBox::information( window(),
								  tr( "Adjuster" ),
								  e.getMessage()
								);
		return false;
	}
	
		// succes 
    return true;
}
// ---------------------------------------------------------------------------


// ----------------- Window::sendMarkersImage() ------------------------------
void Window::sendMarkersImage()
{
	if( !_autoClient.isConnected() ) return;
	
	try
	{
		if( _pRoiEditor )
		{
			if( _pRoiEditor->isStartMarkerVisible() && _pRoiEditor->isEndMarkerVisible() )
			{
				_autoClient.sendMarkersImage( _pRoiEditor->markersImage() );
			}
		}
	}
	catch( const GException & e )
	{
		message( tr( "Camera error: %1" ).arg( e.getMessage() ) );
	}
}
// ---------------------------------------------------------------------------


// ----------------- Window::sendShutterImage() ------------------------------
void Window::sendShutterImage()
{
	if( !_autoClient.isConnected() ) return;
	
	try
	{
		if( _pRoiEditor )
		{
			if( _pRoiEditor->isShutterMarkerVisible() )
			{
				_autoClient.sendShutterImage( _pRoiEditor->shutterImage() );
			}
		}
	}
	catch( const GException & e )
	{
		message( tr( "Camera error: %1" ).arg( e.getMessage() ) );
	}
}
// ---------------------------------------------------------------------------


// --------------------- Window::sendRoiImage() ------------------------------
void Window::sendRoiImage()
{
	if( !_autoClient.isConnected() ) return;
	
	try
	{
		if( _pRoiEditor )
		{
			if( _pRoiEditor->isRoiToolVisible() )
			{
				_autoClient.sendRoiImage( _pRoiEditor->roiImage() );
			}
		}
	}
	catch( const GException & e )
	{
		message( tr( "Camera error: %1" ).arg( e.getMessage() ) );
	}
}
// ---------------------------------------------------------------------------



// eof
